//#include "Field.h"
//#include "Mesh/Mesh.h"
//#include "Mesh/ParallelMesh.h"
//#include "Time/SimulationTime.h"
//
//template<class Type>
//Field<Type>::Field(string name_, Config* config_, ParallelMPI* pmpi_, Space *space_) :
//    name(name_),
//    config(config_),
//    pmpi(pmpi_),
//    space(space_),
//    mesh(space_->mesh)
//{
//    cell_field = NULL;
//    
//    data.resize(mesh->numberPoint);
//    data_average.resize(mesh->numberPoint);
//
//    data_average_global.resize(mesh->numberPointSerial);
//    data_global.resize(mesh->numberPointSerial);
//    data_global_temp.resize(mesh->numberPointSerial);
//    for (int i = 0; i < data_global_temp.size(); i++)
//    {
//        data_global_temp[i] = 0.0;
//    }
//
//
//
//    is_cal_global = true;
//    is_cal_average = true;
//
//    if(config->debugLevel > 1) log_info << "field name: " << name;
//
//    //===================== field boundary condition ===========================
//    for(int i = 0; i < config->em_param.fbc_param.size(); i++)
//    {
//        if(config->em_param.fbc_param[i]->field_name == name)
//        {
//            if (config->debugLevel > 1) log_info<<"init field boundary condition " << config->em_param.fbc_param[i]->field_name<<" "<< config->em_param.fbc_param[i]->fbc_name;
//            fbc_param[config->em_param.fbc_param[i]->fbc_name] = config->em_param.fbc_param[i];
//            //fbc_param[config->em_param.fbc_param[i]->fbc_name]->compile();
//            //log_info << "---- " << config->em_param.fbc_param[i]->fbc_name;
//        }
//    }
//
//
//    //对于输入文件中没有设置场边界条件的边界，也需要创建个none类型的边界条件，用于记录吸收电流等参数
//    if (config->dimension == 3)
//    {
//        for (auto iter = mesh->faceGroupMap.begin(); iter != mesh->faceGroupMap.end(); iter++)
//        {
//            auto faceGroupName = iter->first;
//
//            auto fbcIter = fbc_param.find(faceGroupName);
//            if (fbcIter == fbc_param.end())
//            {
//                //log_info << "faceGroupName---: " << faceGroupName;
//                FieldBoundaryConditionParameter* fieldBoundaryConditionParameter = new FieldBoundaryConditionParameter();
//                fieldBoundaryConditionParameter->field_name = "electric_potential";
//                fieldBoundaryConditionParameter->fbc_type = "none";
//                fbc_param[faceGroupName] = fieldBoundaryConditionParameter;
//            }
//            else
//            {
//                continue;
//            }
//        }
//    }
//    else if (config->dimension == 2)
//    {
//        for (auto iter = mesh->lineGroupMap.begin(); iter != mesh->lineGroupMap.end(); iter++)
//        {
//            auto faceGroupName = iter->first;
//
//            auto fbcIter = fbc_param.find(faceGroupName);
//            if (fbcIter == fbc_param.end())
//            {
//                FieldBoundaryConditionParameter* fieldBoundaryConditionParameter = new FieldBoundaryConditionParameter();
//                fieldBoundaryConditionParameter->field_name = "electric_potential";
//                fieldBoundaryConditionParameter->fbc_type = "none";
//                fbc_param[faceGroupName] = fieldBoundaryConditionParameter;
//            }
//            else
//            {
//                continue;
//            }
//        }
//    }
//
//
//
//    //==========================================================================
//
//    if (config->debugLevel > 1) log_warning << "mesh->numberSharePointReduce: " << mesh->numberSharePointReduce << " " << name;
//    every_sharepoint1 = new double[mesh->numberSharePointReduce]();  //������������ ���ڴ��sharepoint��ֵ�����ڹ�Լ�����ֵ��ÿ������
//    sum_sharepoint1 = new double[mesh->numberSharePointReduce]();
//
//    number_field = NULL;
//
//}
//
//
//template<class Type>
//Field<Type>::Field(EasyMesh::ParallelMesh* mesh_) :
//    mesh(mesh_)
//{
//    int vertexes_size = mesh->pointList.size();
//    data.resize(vertexes_size);
//
//    config = NULL;
//}
//
//
//template<class Type>
//Field<Type>::~Field()
//{
//    //delete[] every_sharepoint1;
//    //delete[] sum_sharepoint1;
//
//    //log_info<<"destroying field";
//}
//
//
//template<class Type>
//void Field<Type>::setData(Type* dataIn)
//{
//    for (int i = 0; i < data.size(); i++)
//    {
//        data[i] = dataIn[i];
//    }
//}
//
//
//template<class Type>
//Type Field<Type>::getValue(int iVolume, const EasyMesh::Point& point)
//{
//
//}
//
//template<>
//double Field<double>::getValue(int iVolume, const EasyMesh::Point& point)
//{
//    if (config->dimension == 3)
//    {
//        Eigen::Matrix4d& bc_coord_inv = mesh->barycentric_coordinate_A_inv[iVolume];
//        Eigen::Vector4d x;
//        Eigen::Vector4d bc;
//
//        for (int i = 0; i < 3; i++)
//        {
//            x(i) = point.position[i];
//        }
//        x(3) = 1.0;
//
//        bc = bc_coord_inv * x;
//
//        double valueTemp = 0.0;
//        for (int iPointLocal = 0; iPointLocal < 4; iPointLocal++)
//        {
//            int iPointGlobal = mesh->volumeList[iVolume].pointList[iPointLocal];
//            valueTemp += data[iPointGlobal] * bc(iPointLocal);
//        }
//        return valueTemp;
//    }
//    else if (config->dimension == 2)
//    {
//        Eigen::Matrix3d& bc_coord_inv = mesh->barycentric_coordinate_A_inv2d[iVolume];
//        Eigen::Vector3d x;
//        Eigen::Vector3d bc;
//
//        for (int i = 0; i < 2; i++)
//        {
//            x(i) = point.position[i];
//        }
//        x(2) = 1.0;
//
//        bc = bc_coord_inv * x;
//
//        double valueTemp = 0.0;
//        for (int iPointLocal = 0; iPointLocal < 3; iPointLocal++)
//        {
//            int iPointGlobal = mesh->faceList[iVolume].pointList[iPointLocal];
//            valueTemp += data[iPointGlobal] * bc(iPointLocal);
//        }
//        return valueTemp;
//    }
//    else
//    {
//        log_error << "the dimension not support: " << config->dimension;
//        exit(0);
//    }
//
//    
//}
//
//template<>
//FemVector3D Field<FemVector3D>::getValue(int iVolume, const EasyMesh::Point& point)
//{
//
//    if (config->dimension == 3)
//    {
//        Eigen::Matrix4d& bc_coord_inv = mesh->barycentric_coordinate_A_inv[iVolume];
//        Eigen::Vector4d x;
//        Eigen::Vector4d bc;
//
//        for (int i = 0; i < 3; i++)
//        {
//            x(i) = point.position[i];
//        }
//        x(3) = 1.0;
//
//        bc = bc_coord_inv * x;
//
//        FemVector3D valueTemp;
//        valueTemp.x[0] = 0.0;
//        valueTemp.x[1] = 0.0;
//        valueTemp.x[2] = 0.0;
//
//        for (int iPointLocal = 0; iPointLocal < 4; iPointLocal++)
//        {
//            int iPointGlobal = mesh->volumeList[iVolume].pointList[iPointLocal];
//            valueTemp.x[0] += data[iPointGlobal].x[0] * bc(iPointLocal);
//            valueTemp.x[1] += data[iPointGlobal].x[1] * bc(iPointLocal);
//            valueTemp.x[2] += data[iPointGlobal].x[2] * bc(iPointLocal);
//        }
//        return valueTemp;
//    }
//    else if (config->dimension == 2)
//    {
//        Eigen::Matrix3d& bc_coord_inv = mesh->barycentric_coordinate_A_inv2d[iVolume];
//        Eigen::Vector3d x;
//        Eigen::Vector3d bc;
//
//        for (int i = 0; i < 2; i++)
//        {
//            x(i) = point.position[i];
//        }
//        x(2) = 1.0;
//
//        bc = bc_coord_inv * x;
//
//        FemVector3D valueTemp;
//        valueTemp.x[0] = 0.0;
//        valueTemp.x[1] = 0.0;
//        valueTemp.x[2] = 0.0;
//
//        for (int iPointLocal = 0; iPointLocal < 3; iPointLocal++)
//        {
//            int iPointGlobal = mesh->faceList[iVolume].pointList[iPointLocal];
//            valueTemp.x[0] += data[iPointGlobal].x[0] * bc(iPointLocal);
//            valueTemp.x[1] += data[iPointGlobal].x[1] * bc(iPointLocal);
//            valueTemp.x[2] += data[iPointGlobal].x[2] * bc(iPointLocal);
//        }
//        return valueTemp;
//    }
//    else
//    {
//        log_error << "the dimension not support: " << config->dimension;
//        exit(0);
//    }
//}
//
//
//template<class Type>
//Field<Type>* Field<Type>::get_cell_field()
//{
//    Field<Type>*  cell_field = new Field<Type>(mesh);
//    cell_field->resize(mesh->numberCell);
//    return cell_field;
//}
//
//template<>
//Field<double>* Field<double>::get_cell_field()
//{
//    
//    if(cell_field == NULL)
//    {
//        cell_field = new Field<double>(mesh);
//        cell_field->resize(mesh->numberCell);
//    }
//
//
//    if (config->dimension == 3)
//    {
//        for (int i = 0; i < cell_field->size(); i++)
//        {
//            auto& volume = mesh->volumeList[i];
//            double cell_value = 0.0;
//            for (int iPoint = 0; iPoint < 4; iPoint++)
//            {
//                cell_value += data[volume.pointList[iPoint]];
//            }
//            (*cell_field)(i) = cell_value / 4.0;
//        }
//    }
//    else if (config->dimension == 2)
//    {
//        for (int i = 0; i < cell_field->size(); i++)
//        {
//            auto& face = mesh->faceList[i];
//            double cell_value = 0.0;
//            for (int iPoint = 0; iPoint < 3; iPoint++)
//            {
//                cell_value += data[face.pointList[iPoint]];
//            }
//            (*cell_field)(i) = cell_value / 3.0;
//        }
//    }
//    else
//    {
//        log_error << "the dimension not support: " << config->dimension;
//        exit(0);
//    }
//
//    
//
//
//    return cell_field;
//}
//
//
//template<>
//Field<FemVector3D>* Field<FemVector3D>::get_cell_field()
//{
//
//    if (cell_field == NULL)
//    {
//        cell_field = new Field<FemVector3D>(mesh);
//        cell_field->resize(mesh->numberCell);
//    }
//
//
//    if (config->dimension == 3)
//    {
//        for (int i = 0; i < cell_field->size(); i++)
//        {
//            auto& volume = mesh->volumeList[i];
//            FemVector3D cell_value;
//            cell_value = 0.0;
//            for (int iPoint = 0; iPoint < 4; iPoint++)
//            {
//                cell_value += data[volume.pointList[iPoint]];
//            }
//            cell_value /= 4.0;
//            (*cell_field)(i) = cell_value;
//        }
//    }
//    else if (config->dimension == 2)
//    {
//        for (int i = 0; i < cell_field->size(); i++)
//        {
//            auto& face = mesh->faceList[i];
//            FemVector3D cell_value;
//            cell_value = 0.0;
//            for (int iPoint = 0; iPoint < 3; iPoint++)
//            {
//                cell_value += data[face.pointList[iPoint]];
//            }
//            cell_value /= 3.0;
//            (*cell_field)(i) = cell_value;
//        }
//    }
//    else
//    {
//        log_error << "the dimension not support: " << config->dimension;
//        exit(0);
//    }
//
//
//    return cell_field;
//}
//
//template<class Type>
//void Field<Type>::cal_average_field()
//{
//    if (config->sim_time->is_time_io_reset())
//    {
//        for (int i = 0; i < data.size(); i++)
//        {
//            data_average[i] = 0.0;
//        }
//    }
//
//    for (int i = 0; i < data.size(); i++)
//    {
//        data_average[i] += data[i];
//        //log_info << "-------- " << data_average[i].x[0] << " " << data[i].x[0];
//    }
//
//    if (config->sim_time->is_time_io())
//    {
//        for (int i = 0; i < data.size(); i++)
//        {
//            data_average[i] /= config->sim_time->timestep_io;
//        }
//    }
//}
//
//
//template<>
//void Field<FemVector3D>::cal_average_field()
//{
//    if (config->sim_time->is_time_io_reset())
//    {
//        //log_info << "time reset";
//        for (int i = 0; i < data.size(); i++)
//        {
//            data_average[i].x[0] = 0.0;
//            data_average[i].x[1] = 0.0;
//            data_average[i].x[2] = 0.0;
//        }
//    }
//    else
//    {
//        //log_info << "no time reset";
//    }
//
//    for (int i = 0; i < data.size(); i++)
//    {
//        //log_info << "-------- " << data_average[i].x[0];
//        data_average[i].x[0] += data[i].x[0];
//        data_average[i].x[1] += data[i].x[1];
//        data_average[i].x[2] += data[i].x[2];
//        //log_info << "++++++++++ " << data_average[i].x[0];
//    }
//
//    if (config->sim_time->is_time_io())
//    {
//        for (int i = 0; i < data.size(); i++)
//        {
//            data_average[i].x[0] /= config->sim_time->timestep_io;
//            data_average[i].x[1] /= config->sim_time->timestep_io;
//            data_average[i].x[2] /= config->sim_time->timestep_io;
//        }
//    }
//}
//
//
//
//template<class Type>
//void Field<Type>::cal_global_field()
//{
//    
//}
//
//template<>
//void Field<double>::cal_global_field()
//{
//    //log_info << " size: " << data_global_temp.size() << " " << data_global.size() << " " << data_average_global.size() << " " << data.size() << " " << data_average.size();
//    //cal global field for data
//    for (int iPointLocal = 0; iPointLocal < mesh->pointList.size(); iPointLocal++)
//    {
//        int iPointGlobal = mesh->globalPointIndices[iPointLocal];
//        data_global_temp[iPointGlobal] = data[iPointLocal];
//    }
//    pmpi->reduce_sum_double(data_global_temp.data(), data_global.data(), data_global.size());
//
//    for (int iPointGlobal = 0; iPointGlobal < mesh->numberPointSerial; iPointGlobal++)
//    {
//        data_global[iPointGlobal] /= mesh->numberOfProcessPointShared[iPointGlobal];
//    }
//
//
//    //cal global field for data_average
//    for (int iPointLocal = 0; iPointLocal < mesh->pointList.size(); iPointLocal++)
//    {
//        int iPointGlobal = mesh->globalPointIndices[iPointLocal];
//        data_global_temp[iPointGlobal] = data_average[iPointLocal];
//    }
//    pmpi->reduce_sum_double(data_global_temp.data(), data_average_global.data(), data_global.size());
//
//    for (int iPointGlobal = 0; iPointGlobal < mesh->numberPointSerial; iPointGlobal++)
//    {
//        data_average_global[iPointGlobal] /= mesh->numberOfProcessPointShared[iPointGlobal];
//    }
//
//}
//
//template<>
//void Field<FemVector3D>::cal_global_field()
//{
//    //cal global field for data
//    for (int iPointLocal = 0; iPointLocal < mesh->pointList.size(); iPointLocal++)
//    {
//        int iPointGlobal = mesh->globalPointIndices[iPointLocal];
//        data_global_temp[iPointGlobal] = data[iPointLocal];
//    }
//    pmpi->reduce_sum_double(&data_global_temp[0].x[0], &data_global[0].x[0], 3*data_global.size());
//    
//    //if (config->debugLevel > 1) log_info << "---------cal_global_field  " << data_average[0].x[0] << " " << data_global[1].x[0];
//
//    for (int iPointGlobal = 0; iPointGlobal < mesh->numberPointSerial; iPointGlobal++)
//    {
//        data_global[iPointGlobal] /= mesh->numberOfProcessPointShared[iPointGlobal];
//    }
//
//
//    //cal global field for data_average
//    for (int iPointLocal = 0; iPointLocal < mesh->pointList.size(); iPointLocal++)
//    {
//        int iPointGlobal = mesh->globalPointIndices[iPointLocal];
//        data_global_temp[iPointGlobal] = data_average[iPointLocal];
//    }
//    pmpi->reduce_sum_double(&data_global_temp[0].x[0], &data_average_global[0].x[0], 3 * data_global.size());
//
//    //if (config->debugLevel > 1) log_info << "---------cal_global_field  " << data_average_global[0].x[0] << " " << data_average_global[1].x[0];
//
//    for (int iPointGlobal = 0; iPointGlobal < mesh->numberPointSerial; iPointGlobal++)
//    {
//        data_average_global[iPointGlobal] /= mesh->numberOfProcessPointShared[iPointGlobal];
//    }
//}
//
//
//
//template<class Type>
//void Field<Type>::cal_sharepointAllReduce()
//{
//
//}
//
//template<>
//void Field<double>::cal_sharepointAllReduce()
//{
//    for (int i = 0; i < mesh->numberSharePointReduce; i++)
//    {
//        every_sharepoint1[i] = 0.0;
//        sum_sharepoint1[i] = 0.0;
//    }
//
//    for (int tempi = 0; tempi < mesh->numberSharePointPer; tempi++)
//    {
//        every_sharepoint1[mesh->temp_array1[tempi]] = data[mesh->temp_array2[tempi]];
//        //cout << "every_sharepoint1[mesh->temp_array1[tempi]]=" << every_sharepoint1[mesh->temp_array1[tempi]] << "," << mesh->temp_array1[tempi] << "," << tempi << "," << mesh->rank1 << endl;
//
//    }
//
//    MPI_Allreduce(every_sharepoint1, sum_sharepoint1, mesh->numberSharePointReduce, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
//
//    for (int tempi = 0; tempi < mesh->numberSharePointReduce; tempi++)
//    {
//
//        if (mesh->temp_array3[tempi] != -1)
//        {
//            data[mesh->temp_array3[tempi]] = sum_sharepoint1[tempi];
//            //cout << "data[mesh->temp_array3[tempi]]=" << data[mesh->temp_array3[tempi]] << "," << mesh->temp_array3[tempi] << "," << tempi << "," << mesh->rank1 << endl;
//
//        }
//    }
//}
//
//template<class Type>
//void Field<Type>::cal_sharepointEHWeightedAverage()
//{
//
//}
//
//template<>
//void Field<FemVector3D>::cal_sharepointEHWeightedAverage()
//{
//    //log_info << "begin cal_sharepointEHWeightedAverage";
//    for (int j = 0; j < 3; j++)                         //����ʸ����������ά�ȹ�Լƽ����
//    {
//        for (int i = 0; i < mesh->numberSharePointReduce; i++)
//        {
//            //log_info << "---- " << i << " " << mesh->numberSharePointReduce;
//            every_sharepoint1[i] = 0.0;
//            sum_sharepoint1[i] = 0.0;
//        }
//
//        for (int i = 0; i < mesh->numberSharePointPer; i++)                        // ȡfeild����data��ֵ����ʱ�������ڹ�Լ
//        {
//            every_sharepoint1[mesh->temp_array1[i]] = data[mesh->temp_array2[i]].x[j];
//            //cout << "every_sharepoint1[mesh->temp_array1[tempi]]=" << every_sharepoint1[mesh->temp_array1[i]] << "," << mesh->temp_array1[i] << "," << i << "," << mesh->rank1 << endl;
//         }
//
//        MPI_Allreduce(every_sharepoint1, sum_sharepoint1, mesh->numberSharePointReduce, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
//
//        for (int tempi = 0; tempi < mesh->numberSharePointReduce; tempi++)            //��Լ��sum������Ҫ����Ȩ��
//        {
//            sum_sharepoint1[tempi] /= (mesh->sharePointWeightFactor[tempi] * 1.0);
//        }
//
//        for (int tempi = 0; tempi < mesh->numberSharePointReduce; tempi++)            //ƽ����ĳ���ֵ��ÿ������
//        {
//
//            if (mesh->temp_array3[tempi] != -1)
//            {
//                data[mesh->temp_array3[tempi]].x[j] = sum_sharepoint1[tempi];
//                //cout << "data[mesh->temp_array3[tempi]]=" << data[mesh->temp_array3[tempi]].x[j] << "," << mesh->temp_array3[tempi] << "," << tempi << "," << mesh->rank1 << endl;
//            }
//        }
//
//    }
//
//    //log_info << "end cal_sharepointEHWeightedAverage";
//}
//
//template<>
//void Field<double>::cal_sharepointEHWeightedAverage()
//{
//    //log_info << "begin cal_sharepointEHWeightedAverage";
//
//    for (int i = 0; i < mesh->numberSharePointReduce; i++)
//    {
//        //log_info << "---- " << i << " " << mesh->numberSharePointReduce;
//        every_sharepoint1[i] = 0.0;
//        sum_sharepoint1[i] = 0.0;
//    }
//
//    for (int i = 0; i < mesh->numberSharePointPer; i++)                        // ȡfeild����data��ֵ����ʱ�������ڹ�Լ
//    {
//        every_sharepoint1[mesh->temp_array1[i]] = data[mesh->temp_array2[i]];
//        //cout << "every_sharepoint1[mesh->temp_array1[tempi]]=" << every_sharepoint1[mesh->temp_array1[i]] << "," << mesh->temp_array1[i] << "," << i << "," << mesh->rank1 << endl;
//    }
//
//    MPI_Allreduce(every_sharepoint1, sum_sharepoint1, mesh->numberSharePointReduce, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
//
//    for (int tempi = 0; tempi < mesh->numberSharePointReduce; tempi++)            //��Լ��sum������Ҫ����Ȩ��
//    {
//        sum_sharepoint1[tempi] /= (mesh->sharePointWeightFactor[tempi] * 1.0);
//    }
//
//    for (int tempi = 0; tempi < mesh->numberSharePointReduce; tempi++)            //ƽ����ĳ���ֵ��ÿ������
//    {
//
//        if (mesh->temp_array3[tempi] != -1)
//        {
//            data[mesh->temp_array3[tempi]] = sum_sharepoint1[tempi];
//            //cout << "data[mesh->temp_array3[tempi]]=" << data[mesh->temp_array3[tempi]].x[j] << "," << mesh->temp_array3[tempi] << "," << tempi << "," << mesh->rank1 << endl;
//        }
//    }
//
//
//
//    //log_info << "end cal_sharepointEHWeightedAverage";
//}
//
//template<class Type>
//void Field<Type>::cal_sharepointEHWeightedSum()
//{
//
//}
//
//template<>
//void Field<FemVector3D>::cal_sharepointEHWeightedSum()
//{
//    //log_info << "begin cal_sharepointEHWeightedAverage";
//    for (int j = 0; j < 3; j++)                         //����ʸ����������ά�ȹ�Լƽ����
//    {
//        for (int i = 0; i < mesh->numberSharePointReduce; i++)
//        {
//            //log_info << "---- " << i << " " << mesh->numberSharePointReduce;
//            every_sharepoint1[i] = 0.0;
//            sum_sharepoint1[i] = 0.0;
//        }
//
//        for (int i = 0; i < mesh->numberSharePointPer; i++)                        // ȡfeild����data��ֵ����ʱ�������ڹ�Լ
//        {
//            every_sharepoint1[mesh->temp_array1[i]] = data[mesh->temp_array2[i]].x[j];
//            //cout << "every_sharepoint1[mesh->temp_array1[tempi]]=" << every_sharepoint1[mesh->temp_array1[i]] << "," << mesh->temp_array1[i] << "," << i << "," << mesh->rank1 << endl;
//        }
//
//        MPI_Allreduce(every_sharepoint1, sum_sharepoint1, mesh->numberSharePointReduce, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
//
//
//        for (int tempi = 0; tempi < mesh->numberSharePointReduce; tempi++)            //ƽ����ĳ���ֵ��ÿ������
//        {
//
//            if (mesh->temp_array3[tempi] != -1)
//            {
//                data[mesh->temp_array3[tempi]].x[j] = sum_sharepoint1[tempi];
//                //cout << "data[mesh->temp_array3[tempi]]=" << data[mesh->temp_array3[tempi]].x[j] << "," << mesh->temp_array3[tempi] << "," << tempi << "," << mesh->rank1 << endl;
//            }
//        }
//
//    }
//
//    //log_info << "end cal_sharepointEHWeightedAverage";
//}
//
//
//template<class Type>
//void Field<Type>::calGrad(Field<FemVector3D>* vectorField)
//{
//
//}
//
//template<>
//void Field<double>::calGrad(Field<FemVector3D>* vectorField)
//{
//    if (config->dimension == 3)
//    {
//        //log_info << "begin calGrad";
//        if (number_field == NULL)
//        {
//            number_field = new Field<double>(mesh);
//
//            for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//            {
//                (*number_field)(iPoint) = 0.0;
//            }
//
//            for (int iVolume = 0; iVolume < mesh->volumeList.size(); iVolume++)
//            {
//                for (int i_loc = 0; i_loc < 4; i_loc++)
//                {
//                    int i_glb;
//                    space->loc2glb(iVolume, i_loc, i_glb);
//                    (*number_field)(i_glb) += 1.0;
//                }
//
//            }
//        }
//
//        //log_info << "1111 calGrad " << vectorField->size() << " " << number_field->size();
//        for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//        {
//            (*vectorField)(iPoint).x[0] = 0.0;
//            (*vectorField)(iPoint).x[1] = 0.0;
//            (*vectorField)(iPoint).x[2] = 0.0;
//        }
//
//
//        //log_info << "2222 calGrad " << vectorField->size() << " " << number_field->size();
//        for (int iVolume = 0; iVolume < mesh->volumeList.size(); iVolume++)
//        {
//            FemVector3D vec3d;
//            vec3d.x[0] = 0.0;
//            vec3d.x[1] = 0.0;
//            vec3d.x[2] = 0.0;
//
//            for (int i_loc = 0; i_loc < 4; i_loc++)
//            {
//                int i_glb;
//                space->loc2glb(iVolume, i_loc, i_glb);
//                vec3d.x[0] += space->space_basic_function[iVolume].b[i_loc] * (*this)(i_glb);
//                vec3d.x[1] += space->space_basic_function[iVolume].c[i_loc] * (*this)(i_glb);
//                vec3d.x[2] += space->space_basic_function[iVolume].d[i_loc] * (*this)(i_glb);
//            }
//            for (int i_loc = 0; i_loc < 4; i_loc++)
//            {
//                int i_glb;
//                space->loc2glb(iVolume, i_loc, i_glb);
//                (*vectorField)(i_glb).x[0] += vec3d.x[0];
//                (*vectorField)(i_glb).x[1] += vec3d.x[1];
//                (*vectorField)(i_glb).x[2] += vec3d.x[2];
//            }
//        }
//
//        //log_info << "3333 calGrad " << vectorField->size() << " " <<number_field->size();
//        for (int i = 0; i < size(); i++)
//        {
//            (*vectorField)(i).x[0] /= (*number_field)(i);
//            (*vectorField)(i).x[1] /= (*number_field)(i);
//            (*vectorField)(i).x[2] /= (*number_field)(i);
//
//            //log_info<<"grad: "<<(*field)(i)<<" "<<(*vec3d_field)(i).x[0]<<" "<<(*vec3d_field)(i).x[1];
//        }
//        //log_info << "end calGrad";
//    }
//    else if (config->dimension == 2)
//    {
//        if (config->debugLevel > 1) log_info << "begin calGrad";
//        if (number_field == NULL)
//        {
//            number_field = new Field<double>(mesh);
//
//            for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//            {
//                (*number_field)(iPoint) = 0.0;
//            }
//
//            for (int iFace = 0; iFace < mesh->faceList.size(); iFace++)
//            {
//                EasyMesh::Face& face = mesh->faceList[iFace];
//                for (int i_loc = 0; i_loc < 3; i_loc++)
//                {
//                    int i_glb = face.pointList[i_loc];
//                    (*number_field)(i_glb) += 1.0;
//                }
//
//            }
//        }
//
//        //log_info << "1111 calGrad " << vectorField->size() << " " << number_field->size();
//        for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//        {
//            (*vectorField)(iPoint).x[0] = 0.0;
//            (*vectorField)(iPoint).x[1] = 0.0;
//            (*vectorField)(iPoint).x[2] = 0.0;
//        }
//
//
//        //log_info << "2222 calGrad " << vectorField->size() << " " << number_field->size();
//        for (int iFace = 0; iFace < mesh->faceList.size(); iFace++)
//        {
//            FemVector3D vec3d;
//            vec3d.x[0] = 0.0;
//            vec3d.x[1] = 0.0;
//            vec3d.x[2] = 0.0;
//
//            EasyMesh::Face& face = mesh->faceList[iFace];
//
//            for (int i_loc = 0; i_loc < 3; i_loc++)
//            {
//                int i_glb = face.pointList[i_loc];
//                vec3d.x[0] += space->space_basic_function[iFace].b[i_loc] * (*this)(i_glb);
//                vec3d.x[1] += space->space_basic_function[iFace].c[i_loc] * (*this)(i_glb);
//                vec3d.x[2] = 0.0;
//
//                //log_info << "===================";
//                //log_info << vec3d.x[0] << " " << vec3d.x[1];
//                //log_info << (*this)(i_glb);
//                //log_info << space->space_basic_function[iFace].b[i_loc] << " " << space->space_basic_function[iFace].c[i_loc];
//            }
//            for (int i_loc = 0; i_loc < 3; i_loc++)
//            {
//                int i_glb = face.pointList[i_loc];
//                (*vectorField)(i_glb).x[0] += vec3d.x[0];
//                (*vectorField)(i_glb).x[1] += vec3d.x[1];
//                (*vectorField)(i_glb).x[2] = 0.0;
//            }
//        }
//
//        //log_info << "3333 calGrad " << vectorField->size() << " " <<number_field->size();
//        for (int i = 0; i < size(); i++)
//        {
//            (*vectorField)(i).x[0] /= (*number_field)(i);
//            (*vectorField)(i).x[1] /= (*number_field)(i);
//            (*vectorField)(i).x[2] = 0.0;
//
//            //log_info<<"grad: "<<(*field)(i)<<" "<<(*vec3d_field)(i).x[0]<<" "<<(*vec3d_field)(i).x[1];
//        }
//        if (config->debugLevel > 1) log_info << "end calGrad";
//    }
//    else
//    {
//        log_error << "the dimension not support: " << config->dimension;
//        exit(0);
//    }
//
//
//
//
//
//}
//
//
//template<class Type>
//void Field<Type>::calDivergence(Field<double>* scalarField)
//{
//
//}
//
//template<>
//void Field<FemVector3D>::calDivergence(Field<double>* scalarField)
//{
//    if (config->dimension == 3)
//    {
//        //log_info << "begin calDivergence";
//        if (number_field == NULL)
//        {
//            number_field = new Field<double>(mesh);
//
//            for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//            {
//                (*number_field)(iPoint) = 0.0;
//            }
//
//            for (int iVolume = 0; iVolume < mesh->volumeList.size(); iVolume++)
//            {
//                for (int i_loc = 0; i_loc < 4; i_loc++)
//                {
//                    int i_glb = mesh->volumeList[iVolume].pointList[i_loc];
//                    (*number_field)(i_glb) += 1.0;
//                }
//            }
//        }
//
//        //log_info << "1111 calGrad " << vectorField->size() << " " << number_field->size();
//        for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//        {
//            (*scalarField)(iPoint) = 0.0;
//        }
//
//
//        //log_info << "2222 calGrad " << vectorField->size() << " " << number_field->size();
//        for (int iVolume = 0; iVolume < mesh->volumeList.size(); iVolume++)
//        {
//            double scalarValue = 0.0;
//
//            for (int i_loc = 0; i_loc < 4; i_loc++)
//            {
//                int i_glb = mesh->volumeList[iVolume].pointList[i_loc];
//
//                scalarValue += space->space_basic_function[iVolume].b[i_loc] * (*this)(i_glb).x[0];
//                scalarValue += space->space_basic_function[iVolume].c[i_loc] * (*this)(i_glb).x[1];
//                scalarValue += space->space_basic_function[iVolume].d[i_loc] * (*this)(i_glb).x[2];
//            }
//
//            for (int i_loc = 0; i_loc < 4; i_loc++)
//            {
//                int i_glb = mesh->volumeList[iVolume].pointList[i_loc];
//                (*scalarField)(i_glb) += scalarValue;
//            }
//        }
//
//        //log_info << "3333 calGrad " << vectorField->size() << " " <<number_field->size();
//        for (int i = 0; i < size(); i++)
//        {
//            (*scalarField)(i) /= (*number_field)(i);
//
//            //log_info<<"grad: "<<(*field)(i)<<" "<<(*vec3d_field)(i).x[0]<<" "<<(*vec3d_field)(i).x[1];
//        }
//        //log_info << "end calGrad";
//    }
//    else if (config->dimension == 2)
//    {
//        if (config->debugLevel > 1) log_info << "begin calGrad";
//        if (number_field == NULL)
//        {
//            number_field = new Field<double>(mesh);
//
//            for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//            {
//                (*number_field)(iPoint) = 0.0;
//            }
//
//            for (int iFace = 0; iFace < mesh->faceList.size(); iFace++)
//            {
//                EasyMesh::Face& face = mesh->faceList[iFace];
//                for (int i_loc = 0; i_loc < 3; i_loc++)
//                {
//                    int i_glb = face.pointList[i_loc];
//                    (*number_field)(i_glb) += 1.0;
//                }
//
//            }
//        }
//
//        //log_info << "1111 calGrad " << vectorField->size() << " " << number_field->size();
//        for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//        {
//            (*scalarField)(iPoint) = 0.0;
//        }
//
//
//        //log_info << "2222 calGrad " << vectorField->size() << " " << number_field->size();
//        for (int iFace = 0; iFace < mesh->faceList.size(); iFace++)
//        {
//            double scalarValue = 0.0;
//
//            for (int i_loc = 0; i_loc < 3; i_loc++)
//            {
//                int i_glb = mesh->faceList[iFace].pointList[i_loc];
//
//                scalarValue += space->space_basic_function[iFace].b[i_loc] * (*this)(i_glb).x[0];
//                scalarValue += space->space_basic_function[iFace].c[i_loc] * (*this)(i_glb).x[1];
//            }
//
//            for (int i_loc = 0; i_loc < 3; i_loc++)
//            {
//                int i_glb = mesh->faceList[iFace].pointList[i_loc];
//                (*scalarField)(i_glb) += scalarValue;
//            }
//        }
//
//        //log_info << "3333 calGrad " << vectorField->size() << " " <<number_field->size();
//        for (int i = 0; i < size(); i++)
//        {
//            (*scalarField)(i) /= (*number_field)(i);
//        }
//        if (config->debugLevel > 1) log_info << "end calGrad";
//    }
//    else
//    {
//        log_error << "the dimension not support: " << config->dimension;
//        exit(0);
//    }
//
//
//
//
//
//}
//
//
//template<class Type>
//void Field<Type>::calDivergenceInVolumeGroup(Field<double>* scalarField)
//{
//
//}
//
//template<>
//void Field<FemVector3D>::calDivergenceInVolumeGroup(Field<double>* scalarField)
//{
//    if (config->dimension == 3)
//    {
//        if (config->debugLevel > 1) log_info << "begin calDivergence";
//        if (number_field == NULL)
//        {
//            number_field = new Field<double>(mesh);
//
//            for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//            {
//                (*number_field)(iPoint) = 0.0;
//            }
//
//            for (int iVolume = 0; iVolume < mesh->volumeList.size(); iVolume++)
//            {
//                if (mesh->volumeList[iVolume].isInGroup == false)
//                {
//                    continue;
//                }
//                for (int i_loc = 0; i_loc < 4; i_loc++)
//                {
//                    int i_glb = mesh->volumeList[iVolume].pointList[i_loc];
//                    (*number_field)(i_glb) += 1.0;
//                }
//            }
//        }
//        //number_field->cal_sharepointAllReduce();
//
//        //log_info << "1111 calGrad " << vectorField->size() << " " << number_field->size();
//        for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//        {
//            (*scalarField)(iPoint) = 0.0;
//        }
//
//
//        //log_info << "2222 calGrad " << vectorField->size() << " " << number_field->size();
//        for (int iVolume = 0; iVolume < mesh->volumeList.size(); iVolume++)
//        {
//            if (mesh->volumeList[iVolume].isInGroup == false)
//            {
//                continue;
//            }
//
//            double scalarValue = 0.0;
//
//            for (int i_loc = 0; i_loc < 4; i_loc++)
//            {
//                int i_glb = mesh->volumeList[iVolume].pointList[i_loc];
//
//                scalarValue += space->space_basic_function[iVolume].b[i_loc] * (*this)(i_glb).x[0];
//                scalarValue += space->space_basic_function[iVolume].c[i_loc] * (*this)(i_glb).x[1];
//                scalarValue += space->space_basic_function[iVolume].d[i_loc] * (*this)(i_glb).x[2];
//            }
//
//            for (int i_loc = 0; i_loc < 4; i_loc++)
//            {
//                int i_glb = mesh->volumeList[iVolume].pointList[i_loc];
//                (*scalarField)(i_glb) += scalarValue;
//            }
//        }
//        //scalarField->cal_sharepointAllReduce();
//
//        //log_info << "3333 calGrad " << vectorField->size() << " " <<number_field->size();
//        for (int i = 0; i < size(); i++)
//        {
//            if ((*number_field)(i) == 0.0)
//            {
//                continue;
//            }
//            (*scalarField)(i) /= (*number_field)(i);
//
//            //log_info<<"grad: "<<(*field)(i)<<" "<<(*vec3d_field)(i).x[0]<<" "<<(*vec3d_field)(i).x[1];
//        }
//        if (config->debugLevel > 1) log_info << "end calDivergence";
//    }
//    else if (config->dimension == 2)
//    {
//        if (config->debugLevel > 1) log_info << "begin calDivergence";
//
//        if (number_field == NULL)
//        {
//            number_field = new Field<double>(mesh);
//
//            for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//            {
//                (*number_field)(iPoint) = 0.0;
//            }
//
//            for (int iFace = 0; iFace < mesh->faceList.size(); iFace++)
//            {
//                if (mesh->faceList[iFace].isInGroup == false)
//                {
//                    continue;
//                }
//
//                EasyMesh::Face& face = mesh->faceList[iFace];
//                for (int i_loc = 0; i_loc < 3; i_loc++)
//                {
//                    int i_glb = mesh->faceList[iFace].pointList[i_loc];
//                    (*number_field)(i_glb) += 1.0;
//                }
//            }
//        }
//        //if (config->debugLevel > 1) log_info << "0000 calGrad " << scalarField->size() << " " << number_field->size();
//
//        //number_field->cal_sharepointAllReduce();
//
//        //log_info << "1111 calGrad " << scalarField->size() << " " << number_field->size();
//        for (int iPoint = 0; iPoint < mesh->pointList.size(); iPoint++)
//        {
//            (*scalarField)(iPoint) = 0.0;
//        }
//
//
//        //log_info << "2222 calGrad " << scalarField->size() << " " << number_field->size();
//        for (int iFace = 0; iFace < mesh->faceList.size(); iFace++)
//        {
//            if (mesh->faceList[iFace].isInGroup == false)
//            {
//                continue;
//            }
//
//            double scalarValue = 0.0;
//
//            for (int i_loc = 0; i_loc < 3; i_loc++)
//            {
//                int i_glb = mesh->faceList[iFace].pointList[i_loc];
//                //mesh->loc2glb(iFace, i_loc, i_glb);
//                //space->loc2glb(iFace, i_loc, i_glb);
//
//                scalarValue += space->space_basic_function[iFace].b[i_loc] * (*this)(i_glb).x[0];
//                scalarValue += space->space_basic_function[iFace].c[i_loc] * (*this)(i_glb).x[1];
//            }
//
//            for (int i_loc = 0; i_loc < 3; i_loc++)
//            {
//                int i_glb = mesh->faceList[iFace].pointList[i_loc];
//                (*scalarField)(i_glb) += scalarValue;
//            }
//        }
//        //scalarField->cal_sharepointAllReduce();
//
//        //log_info << "3333 calGrad " << scalarField->size() << " " <<number_field->size();
//        for (int i = 0; i < size(); i++)
//        {
//            if ((*number_field)(i) == 0.0)
//            {
//                continue;
//            }
//            (*scalarField)(i) /= (*number_field)(i);
//        }
//        if (config->debugLevel > 1) log_info << "end calDivergence";
//    }
//    else
//    {
//        log_error << "the dimension not support: " << config->dimension;
//        exit(0);
//    }
//
//}
//
//
//
//
//template class Field<double>;
//template class Field<FemVector3D>;
